package storage.v1;

import java.util.ArrayList;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;

import com.onpositive.commons.platform.registry.IAdaptable2;
import com.onpositive.data.IPropertyConstants;
import com.onpositive.mediawiki.propertyparser.ParsedDocument;
import com.onpositive.mediawiki.propertyparser.TextParagraphParser;
import com.onpositive.units.ParsedProperty;
import com.onpositive.units.ParsedSection;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.TextContent;
import com.onpositive.wikitemplate.WikiTemplate;
import com.onpositive.wikitemplate.WikiTemplateManager;

public class TextSectionsExtractor extends AbstractValueExtractor {

	@Override
	public void process( String _text, ParsedDocument pDoc, IParserProvider parserProvider, IAdaptable2 adaptable )
	{
		String text = killTemplates(_text) ;
		String[] splitArray = text.split("\n") ;
		ArrayList<String> documentContent = new ArrayList<String>( splitArray.length ) ;
		for( int i = 0 ; i < splitArray.length ; i++ ){
			String str = splitArray[i].replace("&nbsp;", " ").trim();
			str = str.replaceAll("&thinsp;", " ") ;
			str = StringEscapeUtils.unescapeHtml(str) ;
			str = ParserV2.killComments(str) ;
			documentContent.add( str.trim() ) ;
		}
		
		ArrayList<String> sectionStack = new ArrayList<String>() ;
		ArrayList<String> sectionContent = new ArrayList<String>() ;
		String currentSectionName = "Intro" ;
		
		TextContent textContent = new TextContent( getDefaultComment() ) ;
		ParsedProperty prop = new ParsedProperty( IPropertyConstants.TEXT_CONTENT_PROPERTY_NAME, true ) ;
		pDoc.addProperty( prop ) ;
		prop.addValue(textContent) ; 
		
		int currentSectionLevel = 0 ;	
		for( String line : documentContent )
		{
			if (line == null )
				continue;
			
			if ( line.length() == 0 ){
				sectionContent.add( line ) ;
				continue;
			}
			
			if( !isSectionTitle( line ) )//Character.isJavaIdentifierStart( ch0 ) || ch0 == '*'  )
			{
				//line = killRefs( line ) ;
				String l0 = ParserV2.killPictures( line ) ;
				l0 = TextParagraphParser.parse(  l0  ) ;
				
				int i = -1 ;
				int length = l0.length() ;
				boolean isGood = false ;
				do
				{
					i++;
					if( i == length )
						break ;
					
					char ch = l0.charAt(i) ;
					isGood = Character.isJavaIdentifierPart( ch )
							|| Character.isDigit( ch )
							|| l0.startsWith("[[",i)
							|| l0.startsWith("<ref",i)
							|| l0.startsWith("{{",i)  ;
				}
				while( !isGood ) ;
				
				
				l0 = l0.substring(i).trim() ;
				if( l0.length() == 0 )
					continue ;
				
				sectionContent.add( l0 ) ;
			}
			else{
				{//	new section start
					int nextSectionLevel = 0 ;
					int length = line.length() ;
					for(  ; nextSectionLevel < length && line.charAt( nextSectionLevel ) == '=' ; nextSectionLevel++ ) ;
					if( nextSectionLevel == length )
					{
						sectionContent.add("\n") ;						
					}
					else{
						nextSectionLevel -= 2 ;					
						nextSectionLevel = nextSectionLevel > currentSectionLevel ? currentSectionLevel+1 : nextSectionLevel ;
						try{
						{//finalize last section
							for ( int s = sectionStack.size() ; s > 0 && currentSectionLevel + 1 <= s ; sectionStack.remove( --s ) ) ;
							String parentSectionName = currentSectionLevel > 0 ? sectionStack.get(currentSectionLevel-1) : null ; 
							ParsedSection secValue = new ParsedSection( currentSectionName, parentSectionName, sectionContent, textContent, getDefaultComment() ) ;
							
							if( ((String)secValue.value()).trim().length() != 0 || nextSectionLevel > currentSectionLevel )
								textContent.putSection( secValue ) ;
							
							sectionStack.add( currentSectionName ) ;
							sectionContent.clear() ;
						}
						}catch( ArrayIndexOutOfBoundsException e)
						{
							e.printStackTrace() ;
						}
						
											
						
						currentSectionName = line.replace("=", "").trim() ; 
						currentSectionLevel = nextSectionLevel ;
					}
				}
			}
		}
		String parentSectionName = currentSectionLevel > 0 ? sectionStack.get(currentSectionLevel-1) : null ;
		ParsedSection secValue = new ParsedSection( currentSectionName, parentSectionName, sectionContent, textContent, getDefaultComment()) ;
		
		if( ((String)secValue.value()).trim().length() != 0 )
			textContent.putSection( secValue ) ;

	}	

	private boolean isSectionTitle(String line) {
		
		if( !line.startsWith("=") )
			return false ;
		
		final int l = line.length();
		int halfLength = l / 2 ;
		
		for( int i = 0 ; i < halfLength ; i++ )
		{
			if( (line.charAt(i) == '=' ) != ( line.charAt(l-1-i) == '=' ) )
				return false ;
			
			if( (line.charAt(i) != '=' ) )
				return true ;
		}

		return true;
	}

	WikiTemplateManager templateManager = null ;
	
	private String killTemplates( String text ) {
		int bracketsBlockSize = 2 ;		
		
		if( templateManager == null )
			templateManager = new WikiTemplateManager() ;
		
		ArrayList<Integer> templateBounds = new ArrayList<Integer>() ;
		templateBounds.add( 0 ) ;
		int l = text.length() ;
		int weight = 0 ;
		for( int i = 0 ; i < l ; i++ )
		{
			if( text.startsWith( "{{", i ) )
			{
				int ind0 = text.indexOf( "}}",i ) ;
				int ind1 = text.indexOf( "\n",i ) ;
				if( ind0 > ind1 )
				{
					weight++ ;
					if( weight == 1 )
						templateBounds.add(i) ;
				}
				else
					i = ind0>=0 ? ind0+2 : l ;
			}
			else if ( text.startsWith( "}}", i ) )
			{
				if( weight > 0 )
				{
					weight-- ;
					if( weight == 0 )
						templateBounds.add( i+bracketsBlockSize ) ;
				}
			}
		}
		templateBounds.add( text.length() ) ;
		
		//System.out.print(text+ "\n\n");
		
		StringBuilder builder = new StringBuilder() ;
		for( int i = 0 ; i < templateBounds.size() ; i += 2 ){
			try{
				builder.append( text.substring( templateBounds.get(i), templateBounds.get(i+1) ) ) ;				
			}
			catch( Exception e )
			{
				e.printStackTrace() ;
			}
		}
		
		return builder.toString().trim() ;
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configure(Map<String, Object> params) {}

}
